package main;

import java.util.*;
import java.io.*;
import java.net.*;

import gate.*;
import gate.creole.*;
import gate.util.*;



public class StandAloneAnnie  {

  /** The Corpus Pipeline application to contain ANNIE */
  private SerialAnalyserController annieController;

  /**
   * Initialise the ANNIE system. This creates a "corpus pipeline"
   * application that can be used to run sets of documents through
   * the extraction system.
 * @throws IOException 
   */
  public void initAnnie() throws GateException, IOException {
    Out.prln("Initialising ANNIE...");

    // create a serial analyser controller to run ANNIE with
    annieController =
      (SerialAnalyserController) Factory.createResource(
        "gate.creole.SerialAnalyserController", Factory.newFeatureMap(),
        Factory.newFeatureMap(), "ANNIE_" + Gate.genSym());
    // load each PR(ProcessingResources) as defined in ANNIEConstants
    for(int i = 0; i < ANNIEConstants.PR_NAMES.length; i++) {
      FeatureMap params = Factory.newFeatureMap(); // use default parameters
      ProcessingResource pr = (ProcessingResource)
        Factory.createResource(ANNIEConstants.PR_NAMES[i], params);

      // add the PR to the pipeline controller
      annieController.add(pr);
    } // for each ANNIE PR

    Out.prln("...ANNIE loaded");
  } // initAnnie()

  /** Tell ANNIE's controller about the corpus you want to run on */
  public void setCorpus(Corpus corpus) {
    annieController.setCorpus(corpus);
  } // setCorpus

  /** Run ANNIE */
  public void execute() throws GateException {
    Out.prln("Running ANNIE...");
    annieController.execute();
    Out.prln("...ANNIE complete");
  } // execute()

  public static void main(String args[])
  throws GateException, IOException {
    // initialise the GATE library
    Out.prln("Initialising GATE...");
    Gate.init();

    // Load ANNIE plugin
    File gateHome = Gate.getGateHome();
    File pluginsHome = new File(gateHome, "plugins");
    Gate.getCreoleRegister().registerDirectories(new File(pluginsHome, "ANNIE").toURI().toURL());
    Out.prln("...GATE initialised");

    // initialise ANNIE (this may take several minutes)
    StandAloneAnnie annie = new StandAloneAnnie();
    annie.initAnnie();

    // create a GATE corpus and add a document for each command-line
    // argument
    Corpus corpus = (Corpus) Factory.createResource("gate.corpora.CorpusImpl");
    for(int i = 0; i < args.length; i++) {
      URL u = new File(args[0]).toURI().toURL();
      FeatureMap params = Factory.newFeatureMap();
      params.put("sourceUrl", u);
      params.put("preserveOriginalContent", new Boolean(true));
      params.put("collectRepositioningInfo", new Boolean(true));
      Out.prln("Creating doc for " + u);
      Document document = (Document)
        Factory.createResource("gate.corpora.DocumentImpl", params);
      corpus.add(document);
   } // for each of args

    // tell the pipeline about the corpus and run it
    annie.setCorpus(corpus);
    annie.execute();

    // for each document, get an XML document with the
    // person and location names added
    Iterator<Document> iter = corpus.iterator();
    int count = 0;

    while(iter.hasNext()) {//forEach Document
      Document doc = (Document) iter.next();
      AnnotationSet defaultAnnotSet = doc.getAnnotations();
      Set<String> annotTypesRequired = new HashSet<String>();
      annotTypesRequired.add("Person");
      //annotTypesRequired.add("Location");
      Set<Annotation> peopleAndPlaces =
        new HashSet<Annotation>(defaultAnnotSet.get(annotTypesRequired));

      FeatureMap features = doc.getFeatures();
      String originalContent = (String)
        features.get(GateConstants.ORIGINAL_DOCUMENT_CONTENT_FEATURE_NAME);
//      RepositioningInfo info = (RepositioningInfo)
//        features.get(GateConstants.DOCUMENT_REPOSITIONING_INFO_FEATURE_NAME);

            Iterator<Annotation> it = peopleAndPlaces.iterator();
            Annotation currAnnot;
            SortedAnnotationList sortedAnnotations = new SortedAnnotationList();

            while(it.hasNext()) {
              currAnnot = (Annotation) it.next();
              sortedAnnotations.addSortedExclusive(currAnnot);
            } // while

            long endPosition;
            long startPosition;
            
            for(int i=0; i<sortedAnnotations.size(); ++i) {
              currAnnot = (Annotation) sortedAnnotations.get(i);
              startPosition =
                currAnnot.getStartNode().getOffset().longValue();
              endPosition = currAnnot.getEndNode().getOffset().longValue();
              if(endPosition != -1 && startPosition != -1) {
            	Out.prln(originalContent.substring((int)startPosition, (int)endPosition));
              }
            }
    } // for each doc
  } // main

  /**
   *
   */
  public static class SortedAnnotationList extends Vector {
    public SortedAnnotationList() {
      super();
    } // SortedAnnotationList

    public boolean addSortedExclusive(Annotation annot) {
      Annotation currAnot = null;

      // overlapping check
      for (int i=0; i<size(); ++i) {
        currAnot = (Annotation) get(i);
        if(annot.overlaps(currAnot)) {
          return false;
        } // if
      } // for

      long annotStart = annot.getStartNode().getOffset().longValue();
      long currStart;
      // insert
      for (int i=0; i < size(); ++i) {
        currAnot = (Annotation) get(i);
        currStart = currAnot.getStartNode().getOffset().longValue();
        if(annotStart < currStart) {
          insertElementAt(annot, i);
          /*
           Out.prln("Insert start: "+annotStart+" at position: "+i+" size="+size());
           Out.prln("Current start: "+currStart);
           */
          return true;
        } // if
      } // for

      int size = size();
      insertElementAt(annot, size);
//Out.prln("Insert start: "+annotStart+" at size position: "+size);
      return true;
    } // addSorted
  } // SortedAnnotationList
} // class StandAloneAnnie